package com.cooksys.film_rental.dao;

import java.util.List;

import com.cooksys.film_rental.model.Actor;
import com.cooksys.film_rental.model.Category;
import com.cooksys.film_rental.model.Film;
import com.cooksys.film_rental.model.FilmActor;
import com.cooksys.film_rental.model.FilmCategory;
import com.cooksys.film_rental.model.FilmText;
import com.cooksys.film_rental.model.Inventory;
import com.cooksys.film_rental.model.Language;
import com.cooksys.film_rental.model.Store;

/**
 * Data access object for the {@link Film} class
 * 
 * @author Peter Zastoupil
 * 
 */
public interface FilmDao {

	/**
	 * 
	 * @param filmId
	 *            the filmId to search by
	 * @return a {@link Film} object that corresponds to the given filmId
	 */
	public Film getFilmByFilmId(Short filmId);

	/**
	 * Searches the database for {@link Film} objects that match the given
	 * partial title
	 * 
	 * @param partialTitle
	 *            a String that contains search terms separated by whitespace
	 * @return a List of {@link Film} objects that match the given partial title
	 */
	public List<Film> searchFilmsByPartialTitle(String partialTitle);

	/**
	 * 
	 * @param film
	 *            the {@link Film} for which the number of available copies is
	 *            desired
	 * @return the number of copies of the given Film which are still available
	 */
	public long getNumCopiesAvailable(Film film);

	/**
	 * 
	 * @param film
	 *            the {@link Film} for which the number of checked out copies is
	 *            desired
	 * @return the number of copies of the given Film which are checked out
	 */
	public long getNumCopiesCheckedOut(Film film);

	/**
	 * 
	 * @param filmId
	 *            the filmId to search by
	 * @return the {@link FilmText} object associated with the given Film
	 */
	public FilmText getFilmTextByFilmId(Short filmId);

	/**
	 * 
	 * @param language
	 *            the {@link Language} to search by
	 * @return a List of {@link Film} objects associated with the given language
	 */
	public List<Film> searchFilmsByLanguage(Language language);

	/**
	 * 
	 * @param language
	 *            the original {@link Language} to search by
	 * @return a List of {@link Film} objects associated with the given original
	 *         language
	 */
	public List<Film> searchFilmsByOriginalLanguage(Language originalLanguage);

	/**
	 * 
	 * @param inventory
	 *            the {@link Inventory} to search by
	 * @return the {@link Film} associated with the given inventory
	 */
	public Film getFilmByInventory(Inventory inventory);

	/**
	 * 
	 * @param filmActor
	 *            the {@link FilmActor} to search by
	 * @return the {@link Film} associated with the given filmActor
	 */
	public Film getFilmByFilmActor(FilmActor filmActor);

	/**
	 * 
	 * @param filmCategory
	 *            the {@link FilmCategory} to search by
	 * @return the {@link Film} associated with the given filmCategory
	 */
	public Film getFilmByFilmCategory(FilmCategory filmCategory);

	/**
	 * 
	 * @param actor
	 *            the {@link Actor} to search by
	 * @return a List of {@link Film} objects associated with the given actor
	 */
	public List<Film> searchFilmsByActor(Actor actor);

	/**
	 * 
	 * @param category
	 *            the {@link Category} to search by
	 * @return a List of {@link Film} objects associated with the given category
	 */
	public List<Film> searchFilmsByCategory(Category category);

	/**
	 * 
	 * @return a List of all unique ratings in the database as String objects
	 */
	public List<String> getAllRatings();

	/**
	 * 
	 * @return the length of the {@link Film} object in the database with the
	 *         longest runtime
	 */
	public short getMaxRuntime();

	/**
	 * 
	 * @param partialTitle
	 *            a String that contains search terms separated by whitespace.
	 *            cannot be null or empty.
	 * @param categoryFilter
	 *            a {@link Category} object to filter the results by. can be
	 *            null.
	 * @param actorFilter
	 *            a {@link Actor} object to filter the results by. can be null.
	 * @param languageFilter
	 *            a {@link Language} object to filter the results by. can be
	 *            null.
	 * @param originalLanguageFilter
	 *            a {@link Language} object to filter the results by. can be
	 *            null.
	 * @param ratingFilter
	 *            a String to filter the results by. cannot be null, but can be
	 *            empty.
	 * @param runtimeFilter
	 *            a {@link Category} object to filter the results by. cannot be
	 *            null or empty.
	 * @return a List of {@link Film} objects that match the given search terms
	 *         and filters
	 */
	public List<Film> advancedSearch(String partialTitle,
			Category categoryFilter, Actor actorFilter,
			Language languageFilter, Language originalLanguageFilter,
			String ratingFilter, String runtimeFilter);

	/**
	 * 
	 * @param film
	 *            the {@link Film} object whose availability is to be checked
	 * @param store
	 *            the {@link Store} to be searched for film availabilty
	 * @return <code>true</code> if the given store has a copy of the given film
	 *         in stock, <code>false</code> otherwise
	 */
	public boolean getFilmAvailabilityByStore(Film film, Store store);

}
